<?php
/**
  * 无聊之作：实现任意类实例的任意切面和hook任意方法并运行
  * @version $Id: any_instance_hook_and_run.php 222 2013-05-08 11:29:56Z horseluke@126.com $
  */
class model_test{

	public function update(){
		//echo __METHOD__. "\r\n";
		return true;
	}


}

class hooker_1_model_test{

	function method_hook_before_update(instance_runner $runner){
		//echo __METHOD__. "\r\n";
	}

	function method_hook_after_update(instance_runner $runner){
		//echo __METHOD__. "\r\n";
	}

}


class hooker_2_model_test{

	function method_hook_before_update(instance_runner $runner){
		//echo __METHOD__. "\r\n";
	}

	function method_hook_after_update(instance_runner $runner){
		//echo __METHOD__. "\r\n";
	}

}


class hooker_3_model_test{

	function method_hook_before_update(instance_runner $runner){
		//echo __METHOD__. "\r\n";
	}

	function method_hook_after_update(instance_runner $runner){
		//echo __METHOD__. "\r\n";
	}

}

/**
  * hook容器
  */
class instance_hook_container{

	protected static $hook = array();

	public static function attach($hookInstance){
		self::$hook[] = $hookInstance;
	}

	public static function detach($hookInstance){
		$obj_hash = spl_object_hash($hookInstance);
		foreach(self::$hook as $k => $hook){
			if(spl_object_hash($hook) == $obj_hash){
				unset(self::$hook[$k]);
			}
		}
	}

	public static function return_all_hook(){
		return self::$hook;
	}

	public static function run_hook(instance_runner $runner, $hookname){
		foreach(self::$hook as $hookInatance){
			if(method_exists($hookInatance, $hookname)){
				$hookInatance->{$hookname}($runner);
			}
		}
	}

}

/**
  * 每个类instance一个runner实例
  */
class instance_runner{
	
	public $host = null;

	public $param = null;

	public $result = null;

	public function __construct($host){
		$this->host = $host;
	}

	public function __call($method, $param){
		$this->param = $param;
		$this->result = null;
		
		instance_hook_container::run_hook($this, 'method_hook_before_'. $method);
		$this->result = $this->host->$method($param);
		instance_hook_container::run_hook($this, 'method_hook_after_'. $method);

		return $this->result;

	}

}

$starttime = microtime(true);

instance_hook_container::attach(new hooker_1_model_test());
instance_hook_container::attach(new hooker_2_model_test());
instance_hook_container::attach(new hooker_3_model_test());

for($i = 1; $i <= 50; $i++){
	$runner = new instance_runner(new model_test());
	$runner->update();
}


$processtime_1 = microtime(true) - $starttime;
echo 'hook process sec:'. $processtime_1;

echo "\r\n=========================\r\n";
$starttime_2 = microtime(true);
for($i = 1; $i <= 50; $i++){
	$model = new model_test();
	$model->update();
}
$processtime_2 = microtime(true) - $starttime_2;
echo 'raw process sec:'. $processtime_2;


echo "\r\n============". PHP_VERSION. "=============\r\n";
echo 'hook process is '. ($processtime_1 / $processtime_2). ' times the process times of raw process';